/* 日志系统性能测试
*
*   1.单线程写入 同步日志器输出
*   2.多线程写入 同步日志器输出
*   3.单线程写入 异步日志器输出
*   4.多线程写入 异步日志器输出
*
*/

#include "../LogSystemCode/mylog.h"
#include <thread>
#include <string>
#include <vector>
#include <chrono>


//日志器性能测试
void bench(const std::string& logger_name,size_t thread_n,size_t msg_n,size_t msgsize_n)
{
    //1.获取日志器
    Log::Logger::ptr logger = Log::getLogger(logger_name);
    if(logger.get() == nullptr) 
    {
        std::cout<<"日志器不存在!"<<std::endl;
        return;
    }

    //2.组织指定长度的日志消息
    std::string msg(msgsize_n-1,'*'); //日志消息以 * 字符填充 空出一个字节存放 \0

    //3.创建指定数量的线程
    std::vector<std::thread> threads;
    size_t ave_msg_n = msg_n/thread_n; //平均每一个线程输出的日志数量
    double max_sec = 0; //记录最大耗时
    for(int i = 0;i<thread_n;++i)
    {
            threads.emplace_back([&,i]() {
            //4.线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now(); //记录开始时间
            //5.循环写日志
            for(int k = 0;k<ave_msg_n;++k)
                logger->FATALLOG("%s",msg.c_str());

            auto end = std::chrono::high_resolution_clock::now(); //记录结束时间
            std::chrono::duration<double> cost = end - start; //计算时间差
            //6.线程运行结束 计算并输出耗时 记录最大耗时
            std::cout<<"\t线程:"<<i<<"输出"<<ave_msg_n<<"条日志,耗时"<<cost.count()<<"秒"<<std::endl;
            max_sec = max_sec < cost.count()?cost.count():max_sec;
        });
    }
    for(int i = 0;i<thread_n;++i)
        threads[i].join();

    //7.计算总耗时(每秒输出大小 每秒输出条数 )
    size_t msg_per_sec = msg_n / max_sec; //平均每秒输出的日志数量
    size_t msg_per_size = (msg_n*msgsize_n) / (max_sec*1024); //每秒输出多少KB数据

    //8.输出打印结果
    std::cout<<"\t每秒输出日志"<<msg_per_sec<<"条,每秒输出"<<msg_per_size<<"KB"<<std::endl;
}

//同步日志器测试 - 单线程写入/多线程写入
void sync_bench()
{
    std::unique_ptr<Log::LoggerBuilder> logbuild(new Log::GlobalLoggerBuilder);
    logbuild->buildLoggerType(Log::LoggerType::LOGGER_SYNC); //设置为异步日志器
    logbuild->buildAsyncUnsafe(); //设置为不安全模式 --- 屏蔽落地时的IO影响 只测试CPU和内存对日志写入的影响
    logbuild->buildFormatter("%m%n");
    logbuild->buildLoggerName("sync_logger");
    logbuild->buildSink<Log::FileSink>("./log/test.log");
    logbuild->build();

    //单线程写入
    //std::cout<<"单线程写入同步日志器:\n"; bench("sync_logger",1,1000000,100);
    //多线程写入
    std::cout<<"多线程写入同步日志器:\n"; bench("sync_logger",5,1000000,100);
}

//异步日志器测试 - 单线程写入/多线程写入
void async_bench()
{
    std::unique_ptr<Log::LoggerBuilder> logbuild(new Log::GlobalLoggerBuilder);
    logbuild->buildLoggerType(Log::LoggerType::LOGGER_ASYNC); //设置为异步日志器
    logbuild->buildAsyncUnsafe(); //设置为不安全模式 --- 屏蔽落地时的IO影响 只测试CPU和内存对日志写入的影响
    logbuild->buildFormatter("%m%n");
    logbuild->buildLoggerName("async_logger");
    logbuild->buildSink<Log::FileSink>("./log/test.log");
    logbuild->build();

    //单线程写入
    //std::cout<<"单线程写入异步日志器:\n"; bench("async_logger",1,1000000,100);
    //多线程写入
    std::cout<<"多线程写入异步日志器:\n"; bench("async_logger",5,1000000,100);
}

int main()
{
    async_bench();
    return 0;
}


